package presentation.beans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;

import metier.AffectationAction;
import metier.PersonneAction;
import metier.ProjetAction;
import metier.RoleAction;

import org.primefaces.model.DualListModel;
import org.primefaces.model.timeline.DefaultTimeLine;
import org.primefaces.model.timeline.DefaultTimelineEvent;
import org.primefaces.model.timeline.Timeline;

@SuppressWarnings("serial")
@Named
@SessionScoped
public class ProjetBean implements Serializable {

	/**
	 * @generated
	 */
	private Long idProjet;
	/**
	 * @generated
	 */
	private String descriptionProjet;
	/**
	 * @generated
	 */
	private String nomProjet;

	/**
	 * @generated
	 */
	private java.util.List<TacheBean> tache = new java.util.ArrayList<TacheBean>();

	/**
	 * 
	 */
	private java.util.List<AffectationBean> affectation = new java.util.ArrayList<AffectationBean>();

	/**
	 * 
	 */
	private List<Timeline> gantt;

	private int isUserCP = 0;

	/**
	 * @return
	 */
	public Long getIdProjet() {
		return idProjet;
	}

	/**
	 * @param idProjet
	 */
	public void setIdProjet(final Long idProjet) {
		this.idProjet = idProjet;
	}

	/**
	 * @return
	 */
	public String getDescriptionProjet() {
		return descriptionProjet;
	}

	/**
	 * @param descriptionProjet
	 */
	public void setDescriptionProjet(final String descriptionProjet) {
		this.descriptionProjet = descriptionProjet;
	}

	/**
	 * @return
	 */
	public String getNomProjet() {
		return nomProjet;
	}

	/**
	 * @param nomProjet
	 */
	public void setNomProjet(final String nomProjet) {
		this.nomProjet = nomProjet;
	}

	/**
	 * @return
	 */
	public java.util.List<TacheBean> getTache() {
		return tache;
	}

	/**
	 * @param tache
	 */
	public void setTache(final java.util.List<TacheBean> tache) {
		this.tache = tache;
	}

	/**
	 * @return
	 */
	public java.util.List<AffectationBean> getAffectation() {
		return affectation;
	}

	/**
	 * @param affectation
	 */
	public void setAffectation(final java.util.List<AffectationBean> affectation) {
		this.affectation = affectation;
	}

	/**
	 * @param affectationBean
	 */
	public void addAffectation(final AffectationBean affectationBean) {
		getAffectation().add(affectationBean);
	}

	/**
	 * @param affectationBean
	 */
	public void removeAffectation(final AffectationBean affectationBean) {
		getAffectation().remove(affectationBean);
	}

	/**
	 * @return
	 */
	public List<Timeline> getGantt() {
		return gantt;
	}

	/**
	 * @param gantt
	 */
	public void setGantt(final List<Timeline> gantt) {
		this.gantt = gantt;
	}

	/**
	 * @param isUserCP
	 */
	public void setUserCP(int isUserCP) {
		this.isUserCP = isUserCP;
	}

	/**
	 * @return
	 */
	public int getIsUserCP() {
		return isUserCP;
	}

	/**
	 * 
	 */
	private DualListModel<PersonneBean> affectationUtilisateurs;

	/**
	 * @return
	 */
	public DualListModel<PersonneBean> getAffectationUtilisateurs() {
		return affectationUtilisateurs;
	}

	/**
	 * @param affectationUtilisateurs
	 */
	public void setAffectationUtilisateurs(
			final DualListModel<PersonneBean> affectationUtilisateurs) {
		this.affectationUtilisateurs = affectationUtilisateurs;
	}

	/**
	 * initialisation du constructeur avec les listes de ressource pour la
	 * cr�ation de projet
	 */
	public ProjetBean() {
	}

	/**
	 * @return
	 */

	public String doCreate() {
		ProjetAction projetAction = new ProjetAction();
		final PersonneAction personneAction = new PersonneAction();
		AffectationBean newAffectation = new AffectationBean();
		final RoleAction roleAction = new RoleAction();
		final ArrayList<AffectationBean> affectationsToAdd = new ArrayList<AffectationBean>();
		final ProjetBean projetTemp = projetAction.createProject(this,
				PersonneBean.doGetUserFromSession());
		this.setAffectation(projetTemp.getAffectation());
		this.setIdProjet(projetTemp.getIdProjet());
		final FacesContext facesContext = FacesContext.getCurrentInstance();
		@SuppressWarnings("deprecation")
		final PersonneBean personneBean = (PersonneBean) facesContext
				.getApplication().createValueBinding("#{personneBean}")
				.getValue(facesContext);
		personneBean.updateFromSession();
		newAffectation.setProjet(this);
		newAffectation.setRole(roleAction.getConsultant());
		for (Object idPersonne : affectationUtilisateurs.getSource()) {
			String stringIdPersonne = (String) idPersonne;
			PersonneBean personne = personneAction.getPersonneBeanFromId(Long
					.valueOf(stringIdPersonne));
			newAffectation.setPersonne(personne);
			newAffectation.setProjet(this);
			newAffectation.setRole(roleAction.getConsultant());
			affectationsToAdd.add(newAffectation);
			newAffectation = new AffectationBean();
		}
		// Ajout des affectations
		for (AffectationBean affectationBean : affectationsToAdd) {
			affectation.add(affectationBean);
		}
		projetAction.updateProject(this);
		return "index";
	}

	/**
	 * @return
	 */
	public String doUpdate() {
		final ProjetAction projetAction = new ProjetAction();
		final PersonneAction personneAction = new PersonneAction();
		final AffectationAction affectationAction = new AffectationAction();
		AffectationBean newAffectation = new AffectationBean();
		final RoleAction roleAction = new RoleAction();
		newAffectation.setProjet(this);
		newAffectation.setRole(roleAction.getConsultant());
		final ArrayList<AffectationBean> affectationsToAdd = new ArrayList<AffectationBean>();
		final ArrayList<AffectationBean> affectationsToDelete = new ArrayList<AffectationBean>();
		final FacesContext facesContext = FacesContext.getCurrentInstance();
		final PersonneBean sessionPersonneBean = new PersonneBean()
				.doGetUserFromSession();
		boolean hired = true;
		boolean fired = true;
		// On va chercher les affectations qui ont �t� enlev�e par le CP
		for (AffectationBean affectationBean : affectation) {
			// on parcourt les affections choisies par le CP
			fired = true;
			for (Object idPersonne : affectationUtilisateurs.getSource()) {
				String stringIdPersonne = (String) idPersonne;
				PersonneBean personne = personneAction
						.getPersonneBeanFromId(Long.valueOf(stringIdPersonne));
				// on compare, et si la personne est pr�sente elle sera
				// conserv�e
				// sauf si c'est l'utilisateur courant
				if ((affectationBean.getPersonne().getIdPersonne()
						.equals(personne.getIdPersonne()))
						|| (affectationBean.getPersonne().getIdPersonne()
								.equals(sessionPersonneBean.getIdPersonne()))) {
					fired = false;
				}

			}
			if (fired
					&& (!affectationBean.getPersonne().getIdPersonne()
							.equals(sessionPersonneBean.getIdPersonne()))) {
				affectationsToDelete.add(affectationBean);
			}
		}
		// cette fois on va d�tecter les affectations � ajouter
		for (Object idPersonne : affectationUtilisateurs.getSource()) {
			String stringIdPersonne = (String) idPersonne;
			PersonneBean personne = personneAction.getPersonneBeanFromId(Long
					.valueOf(stringIdPersonne));
			hired = true;
			for (AffectationBean affectationBean : affectation) {
				// on compare, et si la personne est pr�sente elle ne sera pas
				// ajout�e
				if (personne.getIdPersonne().equals(
						affectationBean.getPersonne().getIdPersonne())) {
					hired = false;
				}
			}
			if (hired) {
				newAffectation.setPersonne(personne);
				newAffectation.setProjet(this);
				newAffectation.setRole(roleAction.getConsultant());
				affectationsToAdd.add(newAffectation);
				newAffectation = new AffectationBean();
			}
		}
		// Suppression des affectations
		for (AffectationBean affectationBean : affectationsToDelete) {
			affectation.remove(affectationBean);
			affectationAction.deleteAffectation(affectationBean);
		}
		// Ajout des affectations
		for (AffectationBean affectationBean : affectationsToAdd) {
			affectation.add(affectationBean);
		}
		projetAction.updateProject(this);
		this.updateUser();
		return "index";
	}

	/**
	 * @param action
	 */
	public void loadAffectationUtilisateurs(final String action) {
		final PersonneAdministrationBean personneAdministrationBean = new PersonneAdministrationBean();
		final List<PersonneBean> source = new ArrayList<PersonneBean>();
		final List<PersonneBean> target = new ArrayList<PersonneBean>();
		final HttpServletRequest request = (HttpServletRequest) (FacesContext
				.getCurrentInstance().getExternalContext().getRequest());
		// r�cup�ration de l'utilisateur actuel
		final PersonneBean sessionPersonneBean = (PersonneBean) request
				.getSession().getAttribute("user");
		boolean isAffected = false;
		for (PersonneBean personne : personneAdministrationBean
				.fetchPersonnes()) {
			isAffected = false;
			// ne pas prendre en compte l'utilisateur lui m�me
			if (personne.getIdPersonne() != sessionPersonneBean.getIdPersonne()) {
				// on teste l'affectation au projet
				// on regarde parmis toutes les affections de la personne
				// dans le cas de la cr�ation, la personne n'appartient
				// forc�ment pas au projet
				if (!action.equals("Create")) {
					for (AffectationBean affectation : personne
							.getAffectation()) {
						if (this.idProjet.equals(affectation.getProjet()
								.getIdProjet())) {
							isAffected = true;
						}
					}
				}
				// si l'utilisateur est affect� au projet, on l'ajoute � la
				// source
				if (isAffected) {
					source.add(personne);
				} else {
					target.add(personne);
				}
			}
		}
		// charger la liste de ressources
		affectationUtilisateurs = new DualListModel<PersonneBean>(source,
				target);
	}

	public void flush() {
		this.setAffectation(new ArrayList<AffectationBean>());
		this.setAffectationUtilisateurs(new DualListModel<PersonneBean>());
		this.setDescriptionProjet(null);
		this.setGantt(new ArrayList<Timeline>());
		this.setIdProjet(null);
		this.setNomProjet(null);
		this.setTache(new ArrayList<TacheBean>());
		this.setUserCP(0);
	}

	/**
	 * @return
	 */
	public String doGoCreate() {
		this.flush();
		loadAffectationUtilisateurs("Create");
		return "projectCreation";
	}

	/**
	 * Fonction qui met � jour le bean manag� de l'utilisateur (ses projets,
	 * etc..)
	 */
	@SuppressWarnings("deprecation")
	private void updateUser() {
		final FacesContext facesContext = FacesContext.getCurrentInstance();
		final PersonneBean personneBean = (PersonneBean) facesContext
				.getApplication().createValueBinding("#{personneBean}")
				.getValue(facesContext);
		personneBean.reloadFromDatabase();
	}

	/**
	 * fonction qui charge le managed bean en session scope
	 */
	@SuppressWarnings("deprecation")
	private void loadToSessionScope() {
		final ProjetAction projetAction = new ProjetAction();
		ProjetBean projetBean = projetAction.fetchProjet(this);
		this.setDescriptionProjet(projetBean.getDescriptionProjet());
		this.setIdProjet(projetBean.getIdProjet());
		this.setNomProjet(projetBean.getNomProjet());
		this.setAffectation(projetBean.getAffectation());
		this.setTache(projetBean.getTache());
		projetBean.setGantt(this.gantt);
		projetBean.setUserCP(this.isUserCP);
		projetBean.setAffectationUtilisateurs(affectationUtilisateurs);
		final FacesContext facesContext = FacesContext.getCurrentInstance();
		facesContext.getApplication()
				.createValueBinding("#{sessionScope.projetBean}")
				.setValue(facesContext, projetBean);
	}

	/**
	 * 
	 */
	public void doDelete() {
		final ProjetAction projetAction = new ProjetAction();
		projetAction.deleteProject(this);
		updateUser();
	}

	/**
	 * @return
	 */
	public String doGoUpdate() {
		loadAffectationUtilisateurs("Update");
		this.loadToSessionScope();
		return "projectModification";
	}

	/**
	 * @return
	 */
	public String doGoConsult() {
		final PersonneBean user = PersonneBean.doGetUserFromSession();
		ProjetAction projetAction = new ProjetAction();
		ProjetBean projetBean = projetAction.fetchProjet(this);
		this.affectation = projetBean.getAffectation();
		if (this.getIsUserCP() != 1) {
			for (final AffectationBean affectation : this.affectation) {
				if (affectation.getPersonne().getIdPersonne()
						.equals(user.getIdPersonne())) {
					if (affectation.getRole().getTypeRole() == 0) {
						this.setUserCP(1);
					}
				}
			}
		}
		gantt = new ArrayList<Timeline>();
		final Calendar calendar = Calendar.getInstance();
		final DefaultTimeLine graph = new DefaultTimeLine("graph",
				this.getNomProjet());
		calendar.set(2012, 1, 1);
		graph.setFocusDate(calendar.getTime());
		graph.setInitialZoom(18);
		for (TacheBean tache : this.getTache()) {
			graph.addEvent(new DefaultTimelineEvent(tache.getNomTache(), tache
					.getCommentaireTache(), tache.getDebutTache(), tache
					.getFinTache()));
		}
		gantt.add(graph);
		this.loadToSessionScope();
		return "projectConsultation";
	}

	/**
	 * @return
	 */
	public String doGoToTacheCreation() {
		final FacesContext facesContext = FacesContext.getCurrentInstance();
		final TacheBean tacheBean = new TacheBean();
		tacheBean.setProjet(this);
		tacheBean.loadAffectationUtilisateurs("Create");
		facesContext.getApplication()
				.createValueBinding("#{sessionScope.tacheBean}")
				.setValue(facesContext, tacheBean);
		return "tacheCreation";
	}

	public void reloadFromDatabase() {
		ProjetAction projetAction = new ProjetAction();
		ProjetBean projetBean = projetAction.fetchProjet(this);
		this.setAffectation(projetBean.getAffectation());
		this.setAffectationUtilisateurs(projetBean.getAffectationUtilisateurs());
		this.setDescriptionProjet(projetBean.getDescriptionProjet());
		this.setGantt(projetBean.getGantt());
		this.setIdProjet(projetBean.getIdProjet());
		this.setNomProjet(projetBean.getNomProjet());
		this.setTache(projetBean.getTache());
		this.setUserCP(projetBean.getIsUserCP());
	}

}
